package com.hnkj.caiyunweather.logic

import androidx.lifecycle.liveData
import com.hnkj.caiyunweather.logic.dao.PlaceDao
import com.hnkj.caiyunweather.logic.model.Place
import com.hnkj.caiyunweather.logic.model.Weather
import com.hnkj.caiyunweather.logic.network.WeatherNetWork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import okhttp3.Dispatcher
import kotlin.coroutines.CoroutineContext

object Repostory {

    fun savePlace(place: Place) = PlaceDao.savePlace(place)

    fun getSavedPlace() = PlaceDao.getSavePlace()

    fun isPlaceSaved() = PlaceDao.isPlaceSaved()

    fun searchPlaces(placeName: String) = fire(Dispatchers.IO) {
        val searchPlaces = WeatherNetWork.searchPlaces(placeName)
        if (searchPlaces.status == "ok") {
            val places = searchPlaces.places
            Result.success(places)
        } else {
            Result.failure(RuntimeException("response status is ${searchPlaces.status}"))
        }
    }

    fun refreshWeather(lng: String, lat: String) = fire(Dispatchers.IO) {
        coroutineScope {
            val deferredRealtime = async {
                WeatherNetWork.getRealtimeWeather(lng, lat)
            }
            val deferredDaily = async {
                WeatherNetWork.getDailyWeather(lng, lat)
            }
            val realtimeResponse = deferredRealtime.await()
            val dailyResponse = deferredDaily.await()
            if (realtimeResponse.status == "ok" && dailyResponse.status == "ok") {
                val weather = Weather(realtimeResponse.result.realtime, dailyResponse.result.daily)
                Result.success(weather)
            } else {
                Result.failure(
                        java.lang.RuntimeException(
                                "realtime response status is ${realtimeResponse.status} daily response status is " +
                                        "${dailyResponse.status}"
                        )
                )
            }

        }
    }

    private fun <T> fire(context: CoroutineContext, block: suspend () -> Result<T>) =
            liveData<Result<T>>(context) {
                val result = try {
                    block()
                } catch (e: Exception) {
                    Result.failure<T>(e)
                }
                emit(result)
            }

}